package main

import (
	"fmt"
	"os"
	"runtime"
)

var ostype = runtime.GOOS

type HexFormat struct {
	step int
	len uint8
	addr [2]byte
	types uint8
	data []byte
}

const (
	NUMBER_OF_ONE_LINE = 0x20		
)

func (p *HexFormat)BinFormatEncode() string{
	var check uint8
	buf := fmt.Sprintf(":%02X%02X%02X%02X", p.len, p.addr[0], p.addr[1], p.types)
	
	check = p.len + p.addr[0] + p.addr[1] + p.types; //计算校验和
	for _, d := range p.data {
		buf += fmt.Sprintf("%02X", d)
		check += d
	}
	check = ^check + 1
	buf += fmt.Sprintf("%02X\n", check)
	return buf
}


func (p *HexFormat) encodeExtAddr(low_addr uint32) (uint32, string){
	hign_addr := low_addr & 0xffff0000
	p.addr[0] = 0x00
    p.addr[1] = 0x00
    tmp := make([]byte, 2)
	tmp[0] = uint8((hign_addr & 0xff000000) >> 24)
    tmp[1] = uint8((hign_addr & 0xff0000) >> 16)
    p.data = tmp[0:2]
    p.types = 4                                      
    p.len = 2
    str := p.BinFormatEncode()
    return hign_addr, str
}

func (p *HexFormat) encodeData(low_addr uint32, data []byte) string {
	p.len = uint8(len(data))
	p.addr[0] = uint8((low_addr & 0xff00) >> 8)
    p.addr[1] = uint8(low_addr & 0xff)
    p.types = 0
  
    p.data = data[:]
    str := p.BinFormatEncode()
    return str
}

func (p *HexFormat) encodeEnd() string {
	p.len = 0
	p.addr[0] = 0
    p.addr[1] = 0
    p.types = 1
    p.data = nil
    str := p.BinFormatEncode()
    return str
}

func (p *HexFormat) BinFile2HexFile(path string, base_addr uint32) string{
	var low_addr, hign_addr uint32
	var str string
	filedata := make([]byte, 1024*1024)
    filelen := Buf_read(path, filedata)
	low_addr = base_addr
	if(base_addr> 1024*64) {
		hign_addr = 1
	}
	for i:=0; i< filelen; i+= NUMBER_OF_ONE_LINE{ 
		if (low_addr & 0xffff0000) != hign_addr && hign_addr != 0 {    //只有大于64K以后才写入扩展线性地址，第一次一般是没有
			var strtmp string
			hign_addr, strtmp = p.encodeExtAddr(low_addr)
			str+= strtmp
           // fmt.Println(str)
		}
		n := filelen -i 
		if n > NUMBER_OF_ONE_LINE{
			n = NUMBER_OF_ONE_LINE
		}
		str+= p.encodeData(low_addr, filedata[i:i+n])
		low_addr += NUMBER_OF_ONE_LINE
	}
	
    str+= p.encodeEnd()
	return str

}

func MakePathName(rawPath, fileName string) string {
	var path string
	/*mkdir*/
	if rawPath != "" {
		if ostype == "windows"{
   			path = fmt.Sprintf(".\\%s\\", rawPath) 
		}else if ostype == "linux"{
		    path = fmt.Sprintf("./%s/", rawPath) 
		}
		err := os.MkdirAll(path , 0644)
		if err != nil {
			fmt.Println("creat dir failed", err)
			os.Exit(1)
		} 
		os.Chmod(path, 0644)
	}
	return path + fileName
}


func  Writefile(filePathName string, data []byte, step int) (int) {  
	var fd *os.File
	openFlag := os.O_WRONLY|os.O_CREATE
	if step > 0 {
		openFlag |= os.O_APPEND
	}else {
		openFlag |= os.O_TRUNC
	}
	fd, err := os.OpenFile(filePathName, openFlag, 0644)
	defer fd.Close()
	if err != nil {
		fmt.Println("open file failed", err)
    	os.Exit(1)
	}
	os.Chmod(filePathName, 0644)
	
	/*write file*/
    n, err := fd.Write(data)

    if err != nil {
    	fmt.Println("write file failed", err)
        os.Exit(1)
    }
	return n
}

func (p *HexFormat) ConvertBin2Hex(binPathName, hexPathName string, addr uint32) (int) {  
	fp := p.BinFile2HexFile(binPathName, addr)
	n := Writefile(hexPathName, []byte(fp), p.step)
	p.step++
	return n
}





















